using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Risiko.State;
using Risiko.Rendering;
using Microsoft.Xna.Framework.Input.Touch;
using System.Threading;


namespace Risiko.Logic
{

  public class HumanPlayer : PlayerBehavior
  {
    IInputEvents input;
    //List<TerritoryReference> tappedTerritories;

    public HumanPlayer(Game game)
      : base(game)
    {
      this.EnabledChanged += new EventHandler<EventArgs>(HumanPlayer_EnabledChanged);
    }

    //int num_Attacks = 0;
    void HumanPlayer_EnabledChanged(object sender, EventArgs e)
    {
      if (Enabled)
      {
        gameState.playerStates[(int)selfID].CurrArmiesPlacement = new ArmiesPlacement() { isValid = false };
        gameState.playerStates[(int)selfID].CurrArmiesPlacements = new List<ArmiesPlacement>();
        gameState.playerStates[(int)selfID].CurrAttack = new Attack() { isValid = false };
        gameState.playerStates[(int)selfID].CurrCardMove = new CardMove() { isValid = false };
        gameState.playerStates[(int)selfID].CurrMove = new MoveArmies() { isValid = false };

      //num_Attacks = 0;
      //hasNextAttack = Logic.HasNextMove.No;
      }
    }

    public override void Initialize()
    {
      //tappedTerritories = new List<TerritoryReference>();
      base.Initialize();
    }

    public override void Update(GameTime gameTime)
    {
      if (gameState.previousPhase != gameState.gamePhase)
      {
        //if (gameState.gamePhase != GamePhase.ConquerMove)
        //tappedTerritories.Clear();
        gameState.playerStates[(int)selfID].tappedTerritories.Clear();
      }

      GetInput();

      switch (gameState.gamePhase)
      {
        case GamePhase.Reinforcements:
          break;
        case GamePhase.PlayCards:
          if (gameState.gamePhase != gameState.previousPhase)
            gameState.playerStates[(int)selfID].CurrCardMove = base.ComputeCardCombinations();
          PrepareCardMove();
          break;
        case GamePhase.ArmiesPlacement:
          PreparePlaceReinforcements();
          break;
        case GamePhase.Attack:
          PrepareAttack();
          if (hasNextAttack == HasNextMove.Yes)
          {
            Async(() =>
              {
                ApplyAttack();
              });
          }
          break;
        case GamePhase.ConquerMove:
          PrepareConquerMove();
          break;
        case GamePhase.StrategicMove:
          PrepareStrategicMove();
          break;

        default:
          break;
      }

      base.Update(gameTime);
    }


    private void GetInput()
    {
      // Gestione dell'input pubblicato dal Rendering
      input = Game.Services.GetService(typeof(IInputEvents)) as IInputEvents;

      // Update tapped territories
      if (input.TouchedTerritory.IsNull == false)
      {
        // A territory has been selected
        var tRef = input.TouchedTerritory.territoryRef;
        // If it was already selected, deselect it
        if (gameState.playerStates[(int)selfID].tappedTerritories.Contains(tRef))
          gameState.playerStates[(int)gameState.currentPlayer].tappedTerritories.Remove(tRef);
        else
          gameState.playerStates[(int)gameState.currentPlayer].tappedTerritories.Add(tRef);
      }
    }

    private void PrepareCardMove()
    {
      if (!(gameState.playerStates[(int)selfID].CurrCardMove.isValid))
        hasCardMove = HasNextMove.No;
      else
      {
        hasCardMove = HasNextMove.Thinking;

        if (input.TouchedConfirmBtn)
          hasCardMove = HasNextMove.Yes;

        if (input.TouchedDeclineBtn)
          hasCardMove = HasNextMove.No;
      }
    }

    private void PreparePlaceReinforcements()
    {
      hasNextMove = Logic.HasNextMove.Thinking;

      if (gameState.playerStates[(int)selfID].reinforcementsNum == 0)
      {
        hasNextMove = Logic.HasNextMove.No;
        return;
      }

      var tappedTerritories = gameState.playerStates[(int)selfID].tappedTerritories;
      if (tappedTerritories.Count == 1)
      {
        Territory t1 = gameState.board.GetTerritory(tappedTerritories.First());

        if (t1.owner == selfID)
        {
          // Aggiorna lo stato
          t1.armies++;
          gameState.playerStates[(int)selfID].reinforcementsNum--;
          gameState.board.continents[t1.continentID].territories[t1.territoryID] = t1;
          
          // Lancia l'animazione
          gameState.playerStates[(int)selfID].CurrArmiesPlacement = new ArmiesPlacement() { territory = t1, numArmies = 1 };
          gameState.playerStates[(int)selfID].MossaFatta = true;
        }

        tappedTerritories.Clear();
      }
    }


    private void PrepareAttack()
    {
      hasNextAttack = Logic.HasNextMove.Thinking;

      // Prepare an attack
      var tappedTerritories = gameState.playerStates[(int)selfID].tappedTerritories;
      if (tappedTerritories.Count == 2)
      {
        Territory t1 = gameState.board.GetTerritory(tappedTerritories.First());
        Territory t2 = gameState.board.GetTerritory(tappedTerritories.Last());
        int ArmiesAttack = 1;
        if (t1.armies == 3) ArmiesAttack = 2;
        if (t1.armies > 3) ArmiesAttack = 3;

        if (t1.armies > 1 && t1.owner == selfID && t2.owner != selfID && t1.neighbors.Contains(tappedTerritories.Last()))
        {
          // The selected territories are valid, prepare an attack
          gameState.playerStates[(int)selfID].CurrAttack = new Attack() { from = tappedTerritories.First(), to = tappedTerritories.Last(), numArmies = ArmiesAttack };
          hasNextAttack = Logic.HasNextMove.Yes;
          tappedTerritories.Remove(tappedTerritories.Last());
        }
        else
        {
          hasNextAttack = Logic.HasNextMove.Thinking;
          tappedTerritories.Clear();
        }
      }

      if (input.TouchedNextBtn)
      {
        hasNextAttack = Logic.HasNextMove.No;
        gameState.playerStates[(int)selfID].CurrAttack = new Attack() { isValid = false };
      }
    }


    private void PrepareConquerMove()
    {
      hasConquerMove = Logic.HasNextMove.Thinking;

      // Prende i territori dell'attacco vincente
      var currAttack = gameState.playerStates[(int)selfID].CurrAttack;
      var tappedTerritories = gameState.playerStates[(int)selfID].tappedTerritories;
      if (tappedTerritories.Count == 1)
      {
        Territory t1;
        Territory t2;
        int minArmies;
        if (tappedTerritories.First().Equals(currAttack.from))
        {
          // L'utente ha selezionato il territorio di origine dell'attacco
          t1 = gameState.board.GetTerritory(currAttack.to);
          t2 = gameState.board.GetTerritory(currAttack.from);
          minArmies = currAttack.numArmies;
        }
        else if (tappedTerritories.First().Equals(currAttack.to))
        {
          // L'utente ha selezionato il territorio di destinazione dell'attacco
          t1 = gameState.board.GetTerritory(currAttack.from);
          t2 = gameState.board.GetTerritory(currAttack.to);
          minArmies = 1;
        }
        else
        {
          // L'utente ha selezionato un territorio non coinvolto nell'attacco: cambia fase
          hasConquerMove = Logic.HasNextMove.No;
          tappedTerritories.Clear();
          return;
        }

        // Controlla che le armate siano maggiori del minimo consentito per la mossa
        // e che il territorio selezionato sia lo stesso
        if (t1.armies > minArmies && t2.ToRef.Equals(tappedTerritories.First()))
        {
          if (input.TouchedTerritory.gesture == GestureType.Tap)
          {
            // Single tap
            t1.armies--;
            t2.armies++;
          }
          else if (input.TouchedTerritory.gesture == GestureType.DoubleTap)
          {
            // Double tap
            t2.armies += (t1.armies - minArmies);
            t1.armies = minArmies;
          }

          // Salva la mossa nello stato
          gameState.board.continents[t1.continentID].territories[t1.territoryID] = t1;
          gameState.board.continents[t2.continentID].territories[t2.territoryID] = t2;

          //hasConquerMove = Logic.HasNextMove.Yes;
        }

        tappedTerritories.Clear();
      }

      // Gestisce la selezione del pulsante Next
      if (input.TouchedNextBtn)
      {
        hasConquerMove = Logic.HasNextMove.No;
        tappedTerritories.Clear();
        gameState.playerStates[(int)selfID].CurrMove = new MoveArmies() { isValid = false };
      }
    }


    private void PrepareStrategicMove()
    {
      hasStrategicMove = Logic.HasNextMove.Thinking;

      MoveArmies currMove = gameState.playerStates[(int)selfID].CurrMove;

      var tappedTerritories = gameState.playerStates[(int)selfID].tappedTerritories;
      // If two territories were tapped, prepare the move
      if (tappedTerritories.Count == 2)
      {
        Territory t1 = gameState.board.GetTerritory(tappedTerritories.First());
        Territory t2 = gameState.board.GetTerritory(tappedTerritories.Last());

        if (t1.owner == selfID && t1.owner == t2.owner && t1.neighbors.Contains(t2.ToRef))
        {
          if (!currMove.isValid)
          {
            // The two territories have just been selected: prepare the move
            currMove.isValid = true;
            currMove.from = tappedTerritories.First();
            currMove.to = tappedTerritories.Last();
            currMove.numArmies = 1;
            gameState.playerStates[(int)selfID].CurrMove = currMove;
          }
        }
        tappedTerritories.Clear();
      }

      // If the move is valid, prepare the MoveArmies struct
      if (tappedTerritories.Count == 1 && currMove.isValid)
      {
        Territory origin, destination;
        if (tappedTerritories.Last().Equals(currMove.from))
        {
          // If the user tapped on the first territory, set it as destination
          origin = gameState.board.GetTerritory(currMove.to);
          destination = gameState.board.GetTerritory(currMove.from);
        }
        else if (tappedTerritories.Last().Equals(currMove.to))
        {
          // If the user tapped on the second territory, set it as destination
          origin = gameState.board.GetTerritory(currMove.from);
          destination = gameState.board.GetTerritory(currMove.to);
        }
        else
        {
          // If the user tapped on a third territory, exit phase
          hasStrategicMove = Logic.HasNextMove.No;
          tappedTerritories.Clear();
          return;
        }

        // Check if there are enough armies to move
        if (origin.armies > 1 && destination.ToRef.Equals(tappedTerritories.Last()))
        {
          if (input.TouchedTerritory.gesture == GestureType.Tap)
          {
            // Handle single tap
            origin.armies--;
            destination.armies++;
          }
          else
          {
            // Handle double tap
            destination.armies += (origin.armies - 1);
            origin.armies = 1;
          }
          gameState.board.continents[origin.continentID].territories[origin.territoryID] = origin;
          gameState.board.continents[destination.continentID].territories[destination.territoryID] = destination;
        }

        tappedTerritories.Clear();
      }

      if (input.TouchedNextBtn)
      {
        hasStrategicMove = Logic.HasNextMove.No;
        tappedTerritories.Clear();
        gameState.playerStates[(int)selfID].CurrMove = new MoveArmies() { isValid = false };
      }
    }


    public override void OnCurrentAttackWon()
    {
      hasNextMove = Logic.HasNextMove.No;
      hasNextAttack = Logic.HasNextMove.Thinking;

      //gameState.playerStates[(int)selfID].MossaFatta = true;

      ////while (gameState.playerStates[(int)selfID].MossaFatta) { Thread.Sleep(10); }
      //while (!gameState.playerStates[(int)selfID].MossaAnimata) { Thread.Sleep(10); }

      base.OnCurrentAttackWon();
    }

    public override void OnCurrentAttackLost()
    {
      hasNextMove = Logic.HasNextMove.No;
      hasNextAttack = Logic.HasNextMove.Thinking;
      base.OnCurrentAttackLost();
    }

    public Attack nextAttack;
    //public override Attack CurrAttack
    //{
    //  get { return gameState.playerStates[(int)selfID].CurrAttack; }
    //}
  }
}
